﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Data;
using System.Xml.Linq;

namespace Lumberjack
{
    public class XMLExport : IExportContest 
    {
        public List<string> columns = new List<string>();
        public List<Tuple<string, string>> rows = new List<Tuple<string, string>>();
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        public string tableName, fileName;

        public XMLExport(string _fileName)
        {
            fileName = _fileName;
        }

        public void newTable(string _tableName)
        {
            tableName = _tableName;
            rows.Clear();
        }

        public void exportTable(Contest c)
        {

            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;

            XmlTextWriter writer = new XmlTextWriter(fileName.Replace(":","_") , System.Text.Encoding.UTF8);
            writer.WriteStartDocument(true);
            writer.WriteStartElement("Contest");
            writer.WriteAttributeString("C_name", c.C_name);
            writer.WriteAttributeString("_date", c.C_date.ToString());
            writer.WriteAttributeString("competition_1", c.competition_1.ToString());
            writer.WriteAttributeString("competition_2", c.competition_2.ToString());
            writer.WriteAttributeString("competition_3", c.competition_3.ToString());
            writer.WriteAttributeString("competition_4", c.competition_4.ToString());
            writer.WriteAttributeString("competition_5", c.competition_5.ToString());


            var res = (from s in CompetitionWindow.ent.Competitor where s.Contest.C_name == c.C_name select s).ToList();
            List<Result_b> lb = new List<Result_b>();
            List<Result_n> ln = new List<Result_n>();

            newTable("Competitor");

            foreach (var s in res)
            {
                rows.Add(new Tuple<string, string>("Id", s.Id.ToString()));
                rows.Add(new Tuple<string, string>("_name", s.C_name));
                rows.Add(new Tuple<string, string>("surname", s.surname));
                rows.Add(new Tuple<string, string>("adm_unit", s.adm_unit.ToString()));
                rows.Add(new Tuple<string, string>("number", s.number.ToString()));

                lb.AddRange((from d in CompetitionWindow.ent.Result_b where d.Competitorid == s.Id select d).ToList());
                ln.AddRange((from d in CompetitionWindow.ent.Result_n where d.Competitorid == s.Id select d).ToList());
            }

            createNodes(writer, 5);
            if (res.Count > 0)
            writer.WriteEndElement();

            newTable("Result_b");

            foreach (var s in lb)
            {
                rows.Add(new Tuple<string, string>("Id", s.Id.ToString()));
                rows.Add(new Tuple<string, string>("value", s.value.ToString()));
                rows.Add(new Tuple<string, string>("Ruleid", s.Ruleid.ToString()));
                rows.Add(new Tuple<string, string>("Competitorid", s.Competitorid.ToString()));
                rows.Add(new Tuple<string, string>("round", s.round.ToString()));
                rows.Add(new Tuple<string, string>("competition", s.competition.ToString()));
            }

            if (lb.Count > 0)
            {
                createNodes(writer, 6);
                writer.WriteEndElement();
            }

            newTable("Result_n");

            foreach (var s in ln)
            {
                rows.Add(new Tuple<string, string>("Id", s.Id.ToString()));
                rows.Add(new Tuple<string, string>("value", s.value.ToString()));
                rows.Add(new Tuple<string, string>("Ruleid", s.Ruleid.ToString()));
                rows.Add(new Tuple<string, string>("Competitorid", s.Competitorid.ToString()));
                rows.Add(new Tuple<string, string>("round", s.round.ToString()));
            }
            if (ln.Count > 0)
            {
                createNodes(writer, 5);
                writer.WriteEndElement();
            }

            writer.WriteEndElement();
            writer.WriteEndDocument();
            writer.Close();

        }

        public int importTables()
        {
            try
            {
                //TODO check if a given contest exists
                tableName = "Competitor";
                List<Competitor> competitors = new List<Competitor>();
                XDocument doc = XDocument.Load(fileName);
                var d = from s in doc.Descendants("Contest") select s;

                Contest cnt = new Contest();
                foreach (var f in d)
                {
                    cnt.C_name = f.Attribute("C_name").Value;
                    cnt.C_date = Convert.ToDateTime(f.Attribute("_date").Value);
                    cnt.competition_1 = Convert.ToByte(f.Attribute("competition_1").Value);
                    cnt.competition_2 = Convert.ToByte(f.Attribute("competition_2").Value);
                    cnt.competition_3 = Convert.ToByte(f.Attribute("competition_3").Value);
                    cnt.competition_4 = Convert.ToByte(f.Attribute("competition_4").Value);
                    cnt.competition_5 = Convert.ToByte(f.Attribute("competition_5").Value);
                }

                if (cnt.C_name == null)
                {
                    return -2;
                }

                var cntst = (from s in CompetitionWindow.ent.Contest where s.C_name == cnt.C_name && s.C_date == cnt.C_date select s).FirstOrDefault();
                if (cntst != null)
                {
                    return -1;
                }

                competitors = (from s in doc.Descendants(tableName)
                               select new Competitor(
                                   s.Element("Id").Value,
                                   s.Element("_name").Value,
                                   s.Element("surname").Value,
                                   s.Element("adm_unit").Value,
                                   "0",
                                   s.Element("number").Value)).ToList();


                tableName = "Result_n";
                List<Result_n> rn = new List<Result_n>();

                try
                {
                    rn = (from s in doc.Descendants(tableName)
                          select new Result_n(
                              s.Element("value").Value,
                              s.Element("Ruleid").Value,
                              s.Element("Competitorid").Value,
                              s.Element("round").Value)).ToList();
                }
                catch (Exception ex)
                { }

                tableName = "Result_b";
                List<Result_b> rb = new List<Result_b>();
                rb = (from s in doc.Descendants(tableName)
                      select new Result_b(
                          s.Element("value").Value,
                          s.Element("Ruleid").Value,
                          s.Element("Competitorid").Value,
                          s.Element("round").Value,
                          s.Element("competition").Value)).ToList();

                CompetitionWindow.ent.Contest.Add(cnt);


                foreach (var z in competitors)
                {
                    z.Contest = cnt;
                    CompetitionWindow.ent.Competitor.Add(z);
                }
                CompetitionWindow.ent.SaveChanges();

                Dictionary<string, int> ids = new Dictionary<string, int>();
                foreach (var z in competitors)
                {
                    ids.Add(z.oldId.ToString(), z.Id);
                }

                foreach (var z in rb)
                {
                    z.Competitorid = ids[z.Competitorid.ToString()];
                    z.Rule = (from s in CompetitionWindow.ent.Rule where s.Id == z.Ruleid select s).FirstOrDefault();
                    CompetitionWindow.ent.Result_b.Add(z);
                }

                foreach (var z in rn)
                {

                    z.Competitorid = ids[z.Competitorid.ToString()];
                    z.Rule = (from s in CompetitionWindow.ent.Rule where s.Id == z.Ruleid select s).FirstOrDefault();
                    CompetitionWindow.ent.Result_n.Add(z);
                }

                CompetitionWindow.ent.SaveChanges();
            }
            catch(Exception ex)
            {
                log.Error(ex.Message, ex);
            }

            return 0;
        }

        private void createNodes(XmlTextWriter writer, int columnNumber)
        {
            writer.WriteStartElement(tableName);
            int i = 0;
            foreach (Tuple<string, string> r in rows)
            {
                if (i % columnNumber == 0 && i != 0)
                {
                    writer.WriteEndElement();
                    writer.WriteStartElement(tableName);
                }
                i++;
                writer.WriteStartElement(r.Item1);
                writer.WriteString(r.Item2);
                writer.WriteEndElement();

            }
       //     writer.WriteEndElement();
        }

        public void exportContest(Contest model)
        {
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;

            XmlTextWriter writer = new XmlTextWriter(fileName, System.Text.Encoding.UTF8);
            writer.WriteStartDocument(true);
            writer.WriteStartElement("Contest");
            writer.WriteAttributeString("C_name", model.C_name);
            writer.WriteAttributeString("_date", model.C_date.ToString());
            writer.WriteAttributeString("competition_1", model.competition_1.ToString());
            writer.WriteAttributeString("competition_2", model.competition_2.ToString());
            writer.WriteAttributeString("competition_3", model.competition_3.ToString());
            writer.WriteAttributeString("competition_4", model.competition_4.ToString());
            writer.WriteAttributeString("competition_5", model.competition_5.ToString());


            var res = (from s in CompetitionWindow.ent.Competitor where s.Contest.C_name == model.C_name select s).ToList();
            List<Result_b> lb = new List<Result_b>();
            List<Result_n> ln = new List<Result_n>();

            newTable("Competitor");

            foreach (var s in res)
            {
                rows.Add(new Tuple<string, string>("Id", s.Id.ToString()));
                rows.Add(new Tuple<string, string>("_name", s.C_name));
                rows.Add(new Tuple<string, string>("surname", s.surname));
                rows.Add(new Tuple<string, string>("adm_unit", s.adm_unit.ToString()));
                rows.Add(new Tuple<string, string>("number", s.number.ToString()));

                lb.AddRange((from d in CompetitionWindow.ent.Result_b where d.Competitorid == s.Id select d).ToList());
                ln.AddRange((from d in CompetitionWindow.ent.Result_n where d.Competitorid == s.Id select d).ToList());
            }

            createNodes(writer, 5);
            if (res.Count > 0)
                writer.WriteEndElement();

            newTable("Result_b");

            foreach (var s in lb)
            {
                rows.Add(new Tuple<string, string>("Id", s.Id.ToString()));
                rows.Add(new Tuple<string, string>("value", s.value.ToString()));
                rows.Add(new Tuple<string, string>("Ruleid", s.Ruleid.ToString()));
                rows.Add(new Tuple<string, string>("Competitorid", s.Competitorid.ToString()));
                rows.Add(new Tuple<string, string>("round", s.round.ToString()));
                rows.Add(new Tuple<string, string>("competition", s.competition.ToString()));
            }

            createNodes(writer, 6);
            if (lb.Count > 0)
                writer.WriteEndElement();

            newTable("Result_n");

            foreach (var s in ln)
            {
                rows.Add(new Tuple<string, string>("Id", s.Id.ToString()));
                rows.Add(new Tuple<string, string>("value", s.value.ToString()));
                rows.Add(new Tuple<string, string>("Ruleid", s.Ruleid.ToString()));
                rows.Add(new Tuple<string, string>("Competitorid", s.Competitorid.ToString()));
                rows.Add(new Tuple<string, string>("round", s.round.ToString()));
            }

            createNodes(writer, 5);
            if (ln.Count > 0)
                writer.WriteEndElement();

            writer.WriteEndElement();
            writer.WriteEndDocument();
            writer.Close();
        }

        public void importContest(string fileName)
        {
            throw new NotImplementedException();
        }
    }
}





//using System.ComponentModel;

//namespace Lumberjack
//{
//    using System;
//    using System.Collections.Generic;

//    public partial class Competitor : INotifyPropertyChanged
//    {
//        public Competitor()
//        {
//            this.Result_b = new HashSet<Result_b>();
//            this.Result_n = new HashSet<Result_n>();
//            this.Result_r = new HashSet<Result_r>();
//        }

//        public Competitor(string _id, string _name, string _surname, string _admUnit, string _idContest, string _number)
//        {
//            Id = Convert.ToInt32(_id);
//            C_name = _name;
//            surname = _surname;
//            adm_unit = Convert.ToByte(_admUnit);
//            id_contest = Convert.ToInt32(_idContest);
//            number = Convert.ToInt32(_number);
//        }

//        public int Id { get; set; }
//        public string C_name { get; set; }
//        public string surname { get; set; }
//        public Nullable<byte> adm_unit { get; set; }
//        public Nullable<int> id_contest { get; set; }
//        public Nullable<int> number { get; set; }
//        private string punkty_val, _punkty1 = "0", _punkty2 = "0", _punkty3 = "0", _punkty4 = "0", _punkty5 = "0";
//        private string czas_val, _czas1 = "0", _czas2 = "0", _czas3 = "0", _czas4 = "0", _czas5 = "0";

//        public string punkty1
//        {
//            get
//            {
//                return _punkty1;
//            }
//            set
//            {
//                _punkty1 = value;
//                punkty = _punkty1;

//            } 
//        }
//        public string punkty2
//        {
//            get
//            {
//                return _punkty2;
//            }
//            set
//            {
//                _punkty2 = value;
//                punkty = _punkty2;

//            }
//        }
//        public string punkty3
//        {
//            get
//            {
//                return _punkty3;
//            }
//            set
//            {
//                _punkty3 = value;
//                punkty = _punkty3;

//            }
//        }
//        public string punkty4
//        {
//            get
//            {
//                return _punkty4;
//            }
//            set
//            {
//                _punkty4 = value;
//                punkty = _punkty4;

//            }
//        }
//        public string punkty5
//        {
//            get
//            {
//                return _punkty5;
//            }
//            set
//            {
//                _punkty5 = value;
//                punkty = _punkty5;
//            }
//        }

//        public string czas1
//        {
//            get
//            {
//                return _czas1;
//            }
//            set
//            {
//                _czas1 = value;
//                czas = _czas1;
//            }
//        }
//        public string czas2
//        {
//            get
//            {
//                return _czas2;
//            }
//            set
//            {
//                _czas2 = value;
//                czas = _czas2;
//            }
//        }
//        public string czas3
//        {
//            get
//            {
//                return _czas3;
//            }
//            set
//            {
//                _czas3 = value;
//                czas = _czas3;
//            }
//        }
//        public string czas4
//        {
//            get
//            {
//                return _czas4;
//            }
//            set
//            {
//                _czas4 = value;
//                czas = _czas4;
//            }
//        }
//        public string czas5
//        {
//            get
//            {
//                return _czas5;
//            }
//            set
//            {
//                _czas5 = value;
//                czas = _czas5;
//            }
//        }

//        public string punkty
//        {
//            get
//            {
//                return punkty_val;
//            }
//            set
//            {
//                punkty_val = value;
//                NotifyPropertyChanged("punkty");
//            }
//        }
//        public string czas
//        {
//            get
//            {
//                return czas_val;
//            }
//            set
//            {
//                czas_val = value;
//                NotifyPropertyChanged("czas");
//            }
//        }

//        public virtual Contest Contest { get; set; }
//        public virtual ICollection<Result_b> Result_b { get; set; }
//        public virtual ICollection<Result_n> Result_n { get; set; }
//        public virtual ICollection<Result_r> Result_r { get; set; }

//        public event PropertyChangedEventHandler PropertyChanged;


//        private void NotifyPropertyChanged(String propertyName = "")
//        {
//            if (PropertyChanged != null)
//            {
//                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
//            }
//        }
//    }
//}
